﻿using IdentityModel;
using Microsoft.IdentityModel.Tokens;
using SXICE.AdminAPI.Models;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;

namespace SXICE.AdminAPI.Utilities
{
    /// <summary>
    /// Jwt帮助类
    /// </summary>
    internal sealed class JwtHelper
    {
        /// <summary>
        /// 角色Key
        /// </summary>
        const string ROLE = "Role";

        public static string GenerateToken(DoctorClaimsPrincipal user, JwtSettings jwtSettings)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(jwtSettings.SecretKey);
            var authTime = DateTime.UtcNow;
            var expiresAt = authTime.AddMinutes(Math.Max(1, jwtSettings.LifeTime));
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                    {
                        new Claim(JwtClaimTypes.Audience, jwtSettings.Audience),
                        new Claim(JwtClaimTypes.Issuer, jwtSettings.Issuer),
                        new Claim(JwtClaimTypes.Id, user.UserId.ToString()),
                        new Claim(ROLE, user.RoleId.ToString()),
                    }),
                NotBefore = authTime,
                Expires = expiresAt,
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }

        /// <summary>
        /// 验证Token
        /// </summary>
        /// <param name="token">要提取信息的token</param>
        /// <param name="jwtSettings">jwt配置信息</param>
        /// <returns>提取的Customer信息</returns>
        public static DoctorClaimsPrincipal ValidateToken(string token, JwtSettings jwtSettings)
        {
            if (string.IsNullOrWhiteSpace(token))
                return null;
            try
            {
                var handler = new JwtSecurityTokenHandler();
                var jwt = handler.ReadJwtToken(token);
                if (null == jwt)
                    return null;
                var validationParameters = new TokenValidationParameters
                {
                    RequireExpirationTime = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.SecretKey)),
                    ValidateIssuer = true,//是否验证Issuer
                    ValidateAudience = true,//是否验证Audience
                    ValidateLifetime = jwtSettings.LifeTime > 0,//是否验证失效时间
                    ValidateIssuerSigningKey = true,//是否验证SecurityKey
                    ValidAudience = jwtSettings.Audience,
                    ValidIssuer = jwtSettings.Issuer
                };
                var principal = handler.ValidateToken(token, validationParameters, out var securityToken);
                if (!principal.Identity.IsAuthenticated || (jwtSettings.LifeTime > 0 && securityToken.ValidTo < DateTime.UtcNow))
                {
                    principal = null;
                    return null;
                }
                return new DoctorClaimsPrincipal(principal)
                {
                    UserId = int.Parse(principal.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Id).Value),
                    RoleId = int.Parse(principal.Claims.FirstOrDefault(c => c.Type == ROLE).Value)
                };
            }
            catch
            {
                return null;
            }
        }
    }
}
